﻿
Imports System.Net
    Imports System.Net.Sockets
    Imports System.Threading
    Imports System.Text

    Imports System.Runtime.InteropServices
    Imports System.Drawing
    Imports System.Drawing.Imaging
    Imports System.IO

Public Class chat
    Dim hostIP As String = Nothing
    Dim listenerThread As Thread
    Dim port As Integer = 1025
    Public Function getLocationIP()
        '检测主机
        Dim HostIP As IPHostEntry
        '检测本地主机的IP地址，
        Dim IPAddress As IPAddress
        '主机名 类型是字符串
        Dim HostName As String
        '获取到了主机名字
        HostName = Dns.GetHostName
        HostIP = Dns.GetHostByName(HostName)
        IPAddress = New IPAddress(HostIP.AddressList(1).Address)
        Return IPAddress.ToString
    End Function
    Public Shared Sub SendData(socket As Socket, data As Byte(), dataType As String)
        ' 添加数据类型头部
        Dim header As Byte() = Encoding.UTF8.GetBytes(dataType & "|" & data.Length.ToString())
        socket.Send(header)
        ' 发送数据
        socket.Send(data)
    End Sub

    '监听器 本地的监听器
    Public Sub startLocationListener()
        '套接字 
        Dim s As Socket = Nothing
        '线程
        Dim MyIP As String
        Dim temp As String
        s = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) '''使用TCP协议
        Dim localEndPoint As New IPEndPoint(IPAddress.Parse(hostIP), port)  '''指定IP和Port
        s.Bind(localEndPoint)
        s.Listen(1000)     '''侦听，最多接受100个连接
        While (True)
            Dim bytes(2048) As Byte   '''用来存储接收到的字节
            Dim ss As Socket = s.Accept()  '''若接收到,则创建一个新的Socket与之连接
            'ss.Receive(bytes)    '''接收数据，若用ss.send(Byte()),则发送数据
            Dim bytesRead As Integer = ss.Receive(bytes)    '''接收数据，若用ss.send(Byte()),则发送数据

            ' 读取头部信息
            Dim header As String = Encoding.UTF8.GetString(bytes, 0, bytesRead)
            Dim parts() As String = header.Split("|"c)
            Dim dataType As String = parts(0)
            Dim dataLength As Integer = Convert.ToInt32(parts(1))

            ' 读取剩余的数据
            ReDim bytes(dataLength - 1)
            bytesRead = 0
            While bytesRead < dataLength
                Dim bytesReceived As Integer = ss.Receive(bytes, bytesRead, dataLength - bytesRead, SocketFlags.None)
                bytesRead += bytesReceived
            End While

            Dim receivedData As Byte() = bytes
            If dataType = "TEXT" Then
                ' 处理文本数据
                Dim text As String = Encoding.UTF8.GetString(receivedData)
                Console.WriteLine("Received Text: " & text)
                temp = "[我来自服务器]" + vbCrLf + text
                Console.WriteLine(temp)
                Try
                    Me.Invoke(New Action(Sub() RichTextBox1.Text = RichTextBox1.Text + temp))
                Catch ex As Exception
                    MsgBox(ex.ToString)
                End Try
            ElseIf dataType = "IMAGE" Then
                ' 处理图片数据
                Using memoryStream As New IO.MemoryStream(receivedData)
                    Dim image As Image = Image.FromStream(memoryStream)
                    Me.Invoke(New Action(Sub() PictureBox2.Image = image))
                    'image.Save("path_to_save_image.jpg", ImageFormat.Bmp)
                End Using
                Console.WriteLine("Received Image and saved.")
                'Me.Invoke(New Action(Sub() PictureBox1.Image = Image)
            Else
                ' 处理其他数据类型
            End If



            'RichTextBox1.Text = RichTextBox1.Text + vbCrLf + Encoding.Unicode.GetString(bytes)
            '' ListBox1.Items.Insert(0, Encoding.Unicode.GetString(bytes)) '''将其插入到列表框的第一项之前
            '''若使用Encoding.ASCII.GetString(bytes),则接收到的中文字符不能正常显示
        End While
    End Sub
    ' 将图像转换为字节数组的函数
    Private Function ImageToByteArray(image As Image) As Byte()
        Using ms As New MemoryStream()
            image.Save(ms, System.Drawing.Imaging.ImageFormat.Png)
            Return ms.ToArray()
        End Using
    End Function

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        'Form表单加载的时候，执行
        hostIP = getLocationIP()
        Label2.Text = hostIP
        Label4.Text = Str(port)
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        '''建立新的线程
        listenerThread = New Thread(AddressOf startLocationListener)
        '''启动线程
        listenerThread.Start()
        Button1.Enabled = False   '''按钮不可用，避免另启线程
    End Sub

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        Dim addressIP As String = hostIP
        Dim addressPort As Integer = 1025
        Dim L1 = Len(TextBox1.Text)
        Dim L2 = Len(TextBox2.Text)
        If L1 > 0 And L2 > 0 Then
            addressIP = TextBox1.Text
            addressPort = TextBox2.Text
        End If
        Try
            Dim bytes(120) As Byte
            Dim sendSocket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
            Dim localEndPoint As New IPEndPoint(IPAddress.Parse(addressIP), addressPort)
            sendSocket.Connect(localEndPoint)
            SendData(sendSocket, Encoding.Unicode.GetBytes(RichTextBox2.Text), "TEXT")
            'sendSocket.Send(Encoding.Unicode.GetBytes(RichTextBox2.Text))
            sendSocket.Close()
            RichTextBox1.Text = RichTextBox1.Text + vbCrLf + RichTextBox2.Text
            RichTextBox2.Text = ""
        Catch ex As Exception
            MsgBox("目标主机未开放，请检查主机监听是否开启。")
        End Try

    End Sub

    Private Sub Button7_Click(sender As Object, e As EventArgs) Handles Button7.Click
        Dim addressIP As String = hostIP
        Dim addressPort As Integer = 1025
        Dim L1 = Len(TextBox1.Text)
        Dim L2 = Len(TextBox2.Text)
        Dim data As Byte()
        If L1 > 0 And L2 > 0 Then
            addressIP = TextBox1.Text
            addressPort = TextBox2.Text
        End If
        Try
            Dim bytes(120) As Byte
            Dim sendSocket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
            Dim localEndPoint As New IPEndPoint(IPAddress.Parse(addressIP), addressPort)
            sendSocket.Connect(localEndPoint)
            ' 将PictureBox中的图像转换为字节数组
            Dim imageBytes As Byte() = ImageToByteArray(PictureBox1.Image)
            SendData(sendSocket, imageBytes, "IMAGE")
            sendSocket.Close()
            'Dim fs As New FileStream(PictureBox2.Image., IO.FileMode.Open, IO.FileAccess.Read)
            'Dim br As New BinaryReader(fs)
            'Dim data(fs.Length) As Byte
            'data = br.ReadBytes(Convert.ToInt32(fs.Length))
            'fs.Close()
            'br.Close()

            'Using memoryStream As New MemoryStream()
            'PictureBox2.Image.Save(memoryStream, ImageFormat.Bmp)
            'data = memoryStream.ToArray()
            'SendData(sendSocket, data, "IMAGE")
            'SendData(Socket, data, "IMAGE")
            'End Using

            'sendSocket.Send(Encoding.Unicode.GetBytes(RichTextBox2.Text))

            'RichTextBox1.Text = RichTextBox1.Text + vbCrLf + RichTextBox2.Text
            'RichTextBox2.Text = ""
        Catch ex As Exception
            MsgBox("目标主机未开放，请检查主机监听是否开启。")
        End Try

    End Sub

    Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
        RichTextBox2.Text = ""
    End Sub

    <DllImport("User32.dll", SetLastError:=True)>
    Public Shared Function PrintWindow(ByVal hwnd As IntPtr, ByVal hdc As IntPtr, ByVal nFlags As UInteger) As Integer
    End Function
    Private Shared Function GetDesktopWindow() As IntPtr
    End Function

    Private Declare Function CreateCompatibleDC Lib "GDI32" (ByVal hDC As Integer) As Integer
    Private Declare Function CreateCompatibleBitmap Lib "GDI32" (ByVal hDC As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer) As Integer
    Private Declare Function SelectObject Lib "GDI32" (ByVal hDC As Integer, ByVal hObject As Integer) As Integer
    Private Declare Function BitBlt Lib "GDI32" (ByVal srchDC As Integer, ByVal srcX As Integer, ByVal srcY As Integer, ByVal srcW As Integer, ByVal srcH As Integer, ByVal desthDC As Integer, ByVal destX As Integer, ByVal destY As Integer, ByVal op As Integer) As Integer
    Private Declare Function DeleteDC Lib "GDI32" (ByVal hDC As Integer) As Integer
    Private Declare Function DeleteObject Lib "GDI32" (ByVal hObj As Integer) As Integer
    Declare Function GetDC Lib "user32" Alias "GetDC" (ByVal hwnd As Integer) As Integer
    Const SRCCOPY As Integer = &HCC0020


    Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
        Dim bitmap01 As Bitmap
        Dim g01 As Graphics
        Try
            bitmap01 = New Bitmap(1872, 909)  '要截图的目标窗体尺寸
            g01 = Graphics.FromImage(bitmap01)
            PrintWindow(Me.Handle, g01.GetHdc, 0)  '  Me.Handle为目标窗体的hwd句柄
            '获取当前桌面的句柄
            'Dim desktopHandle As IntPtr = GetDesktopWindow()
            'PrintWindow(desktopHandle, g01.GetHdc, 0)
            g01.ReleaseHdc()
            PictureBox1.Image = bitmap01
        Catch ex As Exception

        End Try
    End Sub

    Private Sub Button5_Click(sender As Object, e As EventArgs) Handles Button5.Click
        Dim hDC, hMDC As Integer
        Dim hBMP, hBMPOld As Integer
        Dim sw, sh As Integer
        hDC = GetDC(0)
        hMDC = CreateCompatibleDC(hDC)
        sw = Screen.PrimaryScreen.Bounds.Width
        sh = Screen.PrimaryScreen.Bounds.Height
        hBMP = CreateCompatibleBitmap(hDC, sw, sh)
        hBMPOld = SelectObject(hMDC, hBMP)
        BitBlt(hMDC, 0, 0, sw, sh, hDC, 0, 0, SRCCOPY)
        hBMP = SelectObject(hMDC, hBMPOld)


        PictureBox1.Image = Image.FromHbitmap(New IntPtr(hBMP))
        DeleteDC(hDC)
        DeleteDC(hMDC)
        DeleteObject(hBMP)
        Me.Button5.Enabled = True
    End Sub

    Private Sub Button6_Click(sender As Object, e As EventArgs) Handles Button6.Click
        Dim ofd As SaveFileDialog = Me.SaveFileDialog1
        ofd.Filter = "jpg file|*.jpg|bmp file|*.bmp"
        Dim bmp As Bitmap = Me.PictureBox1.Image
        If ofd.ShowDialog = Windows.Forms.DialogResult.OK Then
            bmp.Save(ofd.FileName)
        End If
    End Sub

    Private Sub PictureBox1_Click(sender As Object, e As EventArgs) Handles PictureBox1.Click

    End Sub

    Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
        Me.Button5_Click(sender, e)
        Me.Button7_Click(sender, e)
    End Sub
End Class
